/*
 * This file is part of the Sx Framework Library.
 * 
 * Copyright (C) 2013 University of Colorado Denver
 * <min.choi@ucdenver.edu> <shane.transue@ucdenver.edu>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */
#include <sxFloat.h>
#include <limits>

Sx::Float::Float() {
	this->value = 0.0f;
}

Sx::Float::Float(const Float& f) {
	this->value = f.value;
}

Sx::Float::Float(float value) {
	this->value = value;
}

Sx::Float::Float(double value) {
	this->value = static_cast<float>(value);
}

Sx::Float::Float(short value) {
	this->value = static_cast<float>(value);
}

Sx::Float::Float(int value) {
	this->value = static_cast<float>(value);
}

Sx::Float::Float(long value) {
	this->value = static_cast<float>(value);
}

Sx::Float::~Float() {}

void Sx::Float::set(float value) {
	this->value = value;
}

float Sx::Float::data() const {
	return this->value;
}

Sx::Float::operator float () const {
	return this->value;
}

Sx::Float Sx::Float::Max() {
	return std::numeric_limits<float>::max();
}

Sx::Float Sx::Float::Min() {
	return std::numeric_limits<float>::min();
}

Sx::Float Sx::Float::Infinity() {
	return std::numeric_limits<float>::infinity();
}

/* 
 * This function implementation utilizes the widely published Doom3 rsqrt
 * optimization: Doom3Source[Math.h][~Line: 241]
 */
float Sx::Float::RealSquareRoot(const Float& f) {
	float x = f.value, y, r;
	long i;

	y = x * 0.5f;
	i = *reinterpret_cast<long *>( &x );
	i = 0x5f3759df - ( i >> 1 );
	r = *reinterpret_cast<float *>( &i );
	r = r * ( 1.5f - r * r * y );
	return r;
}

unsigned long Sx::Float::ToUnsignedLong(const Float& f) {
	return static_cast<unsigned long>(f.value);
}

Sx::Float Sx::Float::operator + (const Float& f) {
	return Float(this->value + f.value);
}

Sx::Float Sx::Float::operator + (float f) {
	return Float(this->value + f);
}

Sx::Float Sx::Float::operator - (const Float& f) {
	return Float(this->value - f.value);
}

Sx::Float Sx::Float::operator - (float f) {
	return Float(this->value - f);
}

Sx::Float Sx::Float::operator * (const Float& f) {
	return Float(this->value * f.value);
}

Sx::Float Sx::Float::operator * (float f) {
	return Float(this->value * f);
}

Sx::Float Sx::Float::operator / (const Float& f) {
	return Float(this->value / f.value);
}

Sx::Float Sx::Float::operator / (float f) {
	return Float(this->value / f);
}

void Sx::Float::operator += (const Float& f) {
	this->value += f.value;
}

void Sx::Float::operator += (float f) {
	this->value += f;
}

void Sx::Float::operator -= (const Float& f) {
	this->value -= f.value;
}

void Sx::Float::operator -= (float f) {
	this->value -= f;
}

void Sx::Float::operator *= (const Float& f) {
	this->value *= f.value;
}

void Sx::Float::operator *= (float f) {
	this->value *= f;
}

void Sx::Float::operator /= (const Float& f) {
	this->value /= f.value;
}

void Sx::Float::operator /= (float f) {
	this->value /= f;
}

void Sx::Float::operator = (const Float& f) {
	this->value = f.value;
}

void Sx::Float::operator = (float f) {
	this->value = f;
}

bool Sx::Float::operator == (const Float& f) {
	if ( this->value == f.value ) return true;
	else return false;
}

bool Sx::Float::operator != (const Float& f) {
	if ( this->value == f.value ) return false;
	else return true;
}

bool Sx::Float::operator == (float f) {
	if ( this->value == f ) return true;
	else return false;
}

bool Sx::Float::operator != (float f) {
	if ( this->value == f ) return false;
	else return true;
}

bool Sx::Float::operator <= (const Float& f) {
	if ( this->value <= f.value ) return true;
	else return false;
}

bool Sx::Float::operator <= (float f) {
	if ( this->value <= f ) return true;
	else return false;
}

bool Sx::Float::operator >= (const Float& f) {
	if ( this->value >= f.value ) return true;
	else return false;
}

bool Sx::Float::operator >= (float f) {
	if ( this->value >= f ) return true;
	else return false;
}

bool Sx::Float::operator < (const Float &f) {
	if ( this->value < f.value ) return true;
	else return false;
}

bool Sx::Float::operator < (float f) {
	if ( this->value < f ) return true;
	else return false;
}

bool Sx::Float::operator > (const Float &f) {
	if ( this->value > f.value ) return true;
	else return false;
}

bool Sx::Float::operator > (float f) {
	if ( this->value > f ) return true;
	else return false;
}

Sx::Float operator + (float v, const Sx::Float& f) {
	Sx::Float r(v);
	r += f;
	return r;
}

Sx::Float operator - (float v, const Sx::Float& f) {
	Sx::Float r(v);
	r -= f;
	return r;
}

Sx::Float operator * (float v, const Sx::Float& f) {
	Sx::Float r(v);
	r *= f;
	return r;
}

Sx::Float operator / (float v, const Sx::Float& f) {
	Sx::Float r(v);
	r /= f;
	return r;
}

std::ostream& operator << (std::ostream &out, const Sx::Float& f) {
	out << static_cast<float>(f);
	return out;
}
